//package com.bluebuck.report.common.enums.config;
//
//import cn.hutool.core.collection.ListUtil;
//import org.apache.ibatis.builder.xml.XMLMapperBuilder;
//import org.apache.ibatis.executor.ErrorContext;
//import org.apache.ibatis.io.ResolverUtil;
//import org.apache.ibatis.session.Configuration;
//import org.apache.ibatis.session.SqlSessionFactory;
//import org.apache.ibatis.session.SqlSessionFactoryBuilder;
//import org.apache.ibatis.type.TypeHandlerRegistry;
//import org.mybatis.spring.SqlSessionFactoryBean;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.context.ConfigurableApplicationContext;
//import org.springframework.core.NestedIOException;
//import org.springframework.core.io.Resource;
//import org.springframework.util.ObjectUtils;
//import org.springframework.util.StringUtils;
//
//import java.util.ArrayList;
//import java.util.HashSet;
//import java.util.Set;
//import java.util.concurrent.ConcurrentHashMap;
//
//
///**
// * @author craft
// */
//public class MybatisSqlSessionFactoryBean extends SqlSessionFactoryBean {
//    private static final Logger LOGGER = LoggerFactory.getLogger(MybatisSqlSessionFactoryBean.class);
//
//    /**
//     * 指定需扫描的枚举类所在包的前缀，可以指定多个包，会自动扫描所有子包。分隔符与spring的包路径分隔符兼容。
//     */
//    protected String[] enumBasePackages;
//
//    protected SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//
//    protected Resource[] mapperLocations;
//
//    protected static final ConcurrentHashMap<Class<? extends IEnumValue>, EnumValueTypeHandler<?>> TYPE_HANDLER_CACHE = new ConcurrentHashMap<>();
//
//    @Override
//    public void setSqlSessionFactoryBuilder(SqlSessionFactoryBuilder sqlSessionFactoryBuilder) {
//        super.setSqlSessionFactoryBuilder(
//                // 由于父类sqlSessionFactoryBuilder字段为私有，覆盖次注入方法后，必须给父类手动注入一次
//                sqlSessionFactoryBuilder);
//        this.sqlSessionFactoryBuilder = sqlSessionFactoryBuilder;
//    }
//
//    /**
//     * 覆盖父类，拦截直接注入的mapperLocations，在子类中解析，禁止在父类中解析。
//     */
//    @Override
//    public void setMapperLocations(Resource[] mapperLocations) {
//        this.mapperLocations = mapperLocations;
//    }
//
//    public void setEnumBasePackages(String[] enumBasePackages) {
//        this.enumBasePackages = enumBasePackages;
//    }
//
//    @SuppressWarnings("unchecked")
//    @Override
//    protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
//        SqlSessionFactory oldSqlSessionFactory = super.buildSqlSessionFactory();
//        Configuration configuration = oldSqlSessionFactory.getConfiguration();
//        // 注意：type handler的注册必须在mapperLocations解析之前
//        TypeHandlerRegistry registry = configuration.getTypeHandlerRegistry();
//        ArrayList<String> enumPackages = parseEnumBasePackage();
//
//        String[] objects = enumPackages.toArray(new String[enumPackages.size()]);
//
//        if (null != enumPackages) {
//            Set<Class<? extends IEnumValue>> enumClasses = doScanEnumClass(objects);
//            if (null != enumClasses) {
//                for (Class<? extends IEnumValue> cls : enumClasses) {
//                    // 显示注册枚举处理器
//                    registry.register(cls, getEnumValueTypeHandlerInstance(cls));
//                    if (LOGGER.isDebugEnabled()) {
//                        LOGGER.debug("EnumValueTypeHandler is registered for type " + cls.getName());
//                    }
//                }
//            }
//        }
//
//        if (!ObjectUtils.isEmpty(this.mapperLocations)) {
//            for (Resource mapperLocation : this.mapperLocations) {
//                if (mapperLocation == null) {
//                    continue;
//                }
//
//                try {
//                    XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
//                            configuration, mapperLocation.toString(), configuration.getSqlFragments());
//                    xmlMapperBuilder.parse();
//                } catch (Exception e) {
//                    throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
//                } finally {
//                    ErrorContext.instance().reset();
//                }
//
//                if (LOGGER.isDebugEnabled()) {
//                    LOGGER.debug("Parsed mapper file: '" + mapperLocation + "'");
//                }
//            }
//        } else {
//            if (LOGGER.isDebugEnabled()) {
//                LOGGER.debug("Property 'mapperLocations' was not specified or no matching resources found");
//            }
//        }
//        return this.sqlSessionFactoryBuilder.build(configuration);
//    }
//
//    /**
//     * 获取枚举对应的handler实例，获取后该枚举对应的handle实例被缓存起来
//     */
//    @SuppressWarnings({"unchecked", "rawtypes"})
//    protected EnumValueTypeHandler getEnumValueTypeHandlerInstance(
//            Class<? extends IEnumValue> enumClass) {
//        if (TYPE_HANDLER_CACHE.containsKey(enumClass)) {
//            return TYPE_HANDLER_CACHE.get(enumClass);
//        }
//
//        EnumValueTypeHandler<?> handler = new EnumValueTypeHandler(enumClass);
//        TYPE_HANDLER_CACHE.putIfAbsent(enumClass, handler);
//        return handler;
//    }
//
//    /**
//     * 搜索实现IEnum接口的枚举类
//     */
//    protected Set<Class<? extends IEnumValue>> doScanEnumClass(String... enumBasePackages) {
//
//        Set<Class<? extends IEnumValue>> filterdClasses = new HashSet<>();
//
//        ResolverUtil<IEnumValue> resolverUtil = new ResolverUtil<>();
//        resolverUtil.findImplementations(IEnumValue.class, enumBasePackages);
//
//        Set<Class<? extends IEnumValue>> handlerSet = new HashSet<>(resolverUtil.getClasses());
//        handlerSet.addAll(new JarScanner<IEnumValue>().findImplementations(IEnumValue.class, enumBasePackages));
//
//        for (Class<? extends IEnumValue> type : handlerSet) {
//            if (type.isEnum()) {
//                filterdClasses.add(type);
//            }
//        }
//        return filterdClasses;
//    }
//
//    protected ArrayList<String> parseEnumBasePackage() {
//
//        ArrayList<String> strings1 = new ArrayList<>();
//
//        String[] enumBasePackages = this.enumBasePackages;
//        for (String str:enumBasePackages) {
//            String[] strings = StringUtils.tokenizeToStringArray(str, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
//            strings1.addAll(ListUtil.toList(strings));
//        }
//
//        return strings1;
//    }
//}
